#pragma once
#include <pthread.h>
#include <iostream>
#include <unistd.h>
#include <vector>
#include <semaphore.h>
#include "Task.hpp"
const static int defaultcap=10;
template <class T>
class RingQueue
{
private:
    void P(sem_t &sem) { sem_wait(&sem); }
    void V(sem_t &sem) { sem_post(&sem); }
    void Lock(pthread_mutex_t &mutex) { pthread_mutex_lock(&mutex); }
    void UnLock(pthread_mutex_t &mutex) { pthread_mutex_unlock(&mutex); }
public:
    RingQueue(int cap=defaultcap) :_ringqueue(cap),_cap(cap),_c_pos(0),_p_pos(0)
    {
        sem_init(&_cdata_sem,0,0);
        sem_init(&_pspace_sem,0,cap);
        pthread_mutex_init(&_pmutex,nullptr);
        pthread_mutex_init(&_cmutex,nullptr);
    }
    void Push(const T &in)  // 生产
    {
        P(_pspace_sem);
        Lock(_pmutex);
        _ringqueue[_p_pos] = in;
        //位置后移，维持环形队列
        _p_pos++;
        _p_pos%=_cap;
        UnLock(_pmutex);
        V(_cdata_sem);
    }
    void Pop(T *out)  //消费
    {
        P(_cdata_sem);
        Lock(_cmutex);
        *out=_ringqueue[_c_pos];
        //位置后移，维持环形队列
        _c_pos++;
        _c_pos%=_cap;
        UnLock(_cmutex);
        V(_pspace_sem);
    }
    ~RingQueue() 
    {
        sem_destroy(&_cdata_sem);
        sem_destroy(&_pspace_sem);
        pthread_mutex_destroy(&_cmutex);
        pthread_mutex_destroy(&_pmutex);
    }
private:
    std::vector<T> _ringqueue;
    int _cap;
    int _c_pos; //消费者下标
    int _p_pos; //生产者下标
    sem_t _cdata_sem; //消费者关注的数据资源
    sem_t _pspace_sem; //生产者关注的空间资源
    pthread_mutex_t _pmutex;
    pthread_mutex_t _cmutex;
};


